package mq

import (
	"context"
	"fmt"
	"time"

	"github.com/we-pay-kit/we-pay-kit/internal/logger"
)

// Consumer provides helper to consume messages with handler and retry-on-failure (nack requeue).
type Consumer struct {
	client *RabbitMQClient
}

func NewConsumer() *Consumer { return &Consumer{client: GetRabbitMQ()} }

// ConsumeJSON consumes messages from a queue and passes body to handler.
// Handler should return nil on success; non-nil triggers nack+requeue with backoff.
func (c *Consumer) ConsumeJSON(ctx context.Context, queue string, prefetch int, handler func([]byte) error) error {
	if c.client == nil || c.client.channel == nil {
		return fmt.Errorf("rabbitmq not initialized")
	}

	if _, err := c.client.channel.QueueDeclare(queue, true, false, false, false, nil); err != nil {
		return err
	}

	if err := c.client.channel.Qos(prefetch, 0, false); err != nil {
		return err
	}

	deliveries, err := c.client.channel.Consume(queue, "", false, false, false, false, nil)
	if err != nil {
		return err
	}

	go func() {
		backoff := time.Second
		for {
			select {
			case <-ctx.Done():
				return
			case d, ok := <-deliveries:
				if !ok {
					return
				}
				if err := handler(d.Body); err != nil {
					logger.Error(fmt.Sprintf("consume handler error: %v", err))
					_ = d.Nack(false, true) // requeue
					time.Sleep(backoff)
					if backoff < 30*time.Second {
						backoff *= 2
					}
					continue
				}
				_ = d.Ack(false)
				backoff = time.Second
			}
		}
	}()

	return nil
}
